package com.huangd.platform.common.utils;

import org.springframework.scheduling.support.CronSequenceGenerator;

import java.lang.management.ManagementFactory;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static java.util.Calendar.*;

/**
 * 日期工具类，用于简化程序中的日期处理
 * 
 * @author wing
 * 
 */
public class DateUtils extends org.apache.commons.lang.time.DateUtils {

	/** 日期时间格式:年-月-日 时:分:秒[2011-5-5 20:00:00] */
	public static final String PATTERN_DATE_TIME = "yyyy-MM-dd HH:mm:ss";
	/** 日期格式:年-月-日[2011-05-05] */
	public static final String PATTERN_DATE = "yyyy-MM-dd";
	/** 时间格式:时:分:秒[20:00:00] */
	public static final String PATTERN_TIME = "HH:mm:ss";
	/** 短时间格式:时:分[20:00] */
	public static final String PATTERN_SHORT_TIME = "HH:mm";

	/** 一个很久很久以前的时间(格林威治的起始时间. 1970-01-01 00:00:00) */
	public static final Date LONG_BEFORE_TIME = string2Date("1970-01-01 00:00:00", PATTERN_DATE_TIME);
	/** 一个很久很久以后的时间(该框架可能被遗弃的时间. 2048-01-01 00:00:00) */
	public static final Date LONG_AFTER_TIME = string2Date("2048-01-01 00:00:00", PATTERN_DATE_TIME);

	/**
	 * 检查当前时间和指定时间是否同一周
	 * 
	 * @param year
	 *            年
	 * @param week
	 *            周
	 * @param firstDayOfWeek
	 *            周的第一天设置值，{@link Calendar#DAY_OF_WEEK}
	 * @return
	 */
	public static boolean isSameWeek(int year, int week, int firstDayOfWeek) {
		Calendar cal = Calendar.getInstance();
		cal.setFirstDayOfWeek(firstDayOfWeek);
		return year == cal.get(YEAR) && week == cal.get(WEEK_OF_YEAR);
	}

	/**
	 * 检查当前时间和指定时间是否同一周
	 * 
	 * @param time
	 *            被检查的时间
	 * @param firstDayOfWeek
	 *            周的第一天设置值，{@link Calendar#DAY_OF_WEEK}
	 * @return {@link Boolean} 是否同一周. true-是, false-不是
	 */
	public static boolean isSameWeek(Date time, int firstDayOfWeek) {
		if (time == null) {
			return false;
		}

		Calendar cal = Calendar.getInstance();
		cal.setTime(time);
		cal.setFirstDayOfWeek(firstDayOfWeek);
		return isSameWeek(cal.get(YEAR), cal.get(WEEK_OF_YEAR), firstDayOfWeek);
	}

	/**
	 * 获取周的第一天
	 * 
	 * @param firstDayOfWeek
	 *            周的第一天设置值，{@link Calendar#DAY_OF_WEEK}
	 * @param time
	 *            指定时间，为 null 代表当前时间
	 * @return {@link Date} 周的第一天
	 */
	public static Date firstTimeOfWeek(int firstDayOfWeek, Date time) {
		Calendar cal = Calendar.getInstance();
		if (time != null) {
			cal.setTime(time);
		}

		cal.setFirstDayOfWeek(firstDayOfWeek);
		int day = cal.get(DAY_OF_WEEK);
		if (day == firstDayOfWeek) {
			day = 0;
		} else if (day < firstDayOfWeek) {
			day = day + (7 - firstDayOfWeek);
		} else if (day > firstDayOfWeek) {
			day = day - firstDayOfWeek;
		}

		cal.set(HOUR_OF_DAY, 0);
		cal.set(MINUTE, 0);
		cal.set(SECOND, 0);
		cal.set(MILLISECOND, 0);

		cal.add(DATE, -day);
		return cal.getTime();
	}

	/**
	 * 检查指定日期是否今天(使用系统时间)
	 * 
	 * @param date
	 *            被检查的日期
	 * @return {@link Boolean} 是否今天, true-今天, false-不是今天
	 */
	public static boolean isToday(Date date) {
		if (date == null) {
			return false;
		}
		return isSameDay(date, new Date());
	}

	/**
	 * 日期转换成字符串格式
	 * 
	 * @param date
	 *            待转换的日期
	 * @param pattern
	 *            日期格式
	 * @return {@link String} 日期字符串
	 */
	public static String date2String(Date date, String pattern) {
		if (date == null)
			return null;

		return new SimpleDateFormat(pattern).format(date);
	}

	/**
	 * 字符串转换成日期格式
	 * 
	 * @param string
	 *            待转换的日期字符串
	 * @param pattern
	 *            日期格式
	 * @return {@link Date} 转换后的日期
	 */
	public static Date string2Date(String string, String pattern) {

		if (string == null || string.trim().isEmpty())
			return null;
		try {
			return new SimpleDateFormat(pattern).parse(string);
		} catch (ParseException e) {
			throw new IllegalArgumentException("无法将字符串[" + string + "]按格式[" + pattern + "]转换为日期", e);
		}
	}

	/**
	 * 对一个具体的时间增加时间
	 * 
	 * @param source
	 *            需要修改的时间
	 * @param hours
	 *            需要增加或者减少的小时
	 * @param minutes
	 *            需要增加或者减少的分
	 * @param second
	 *            需要增加或者减少的秒
	 * @return {@link Date} 返回修改过的时间
	 */
	public static Date addTime(Date source, int hours, int minutes, int second) {
		if (source == null) {
			return null;
		}

		Calendar cal = Calendar.getInstance();
		cal.setTime(source);
		cal.add(Calendar.HOUR_OF_DAY, hours);
		cal.add(Calendar.MINUTE, minutes);
		cal.add(Calendar.SECOND, second);
		return cal.getTime();
	}

	/**
	 * 获取某日的开始时间，即获得某一时间的0点
	 * 
	 * @param date
	 *            需要计算的时间
	 */
	public static Date getFirstTime(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.set(Calendar.HOUR_OF_DAY, 0);
		calendar.set(Calendar.MINUTE, 0);
		calendar.set(Calendar.SECOND, 0);
		calendar.set(Calendar.MILLISECOND, 0);
		return calendar.getTime();
	}

	/**
	 * 获得指定时间的下一个0点
	 * 
	 * @param date
	 *            需要计算的时间
	 */
	public static Date getNextDayFirstTime(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTimeInMillis(date.getTime() + MILLIS_PER_DAY);
		calendar.set(Calendar.HOUR_OF_DAY, 0);
		calendar.set(Calendar.MINUTE, 0);
		calendar.set(Calendar.SECOND, 0);
		return calendar.getTime();
	}

	/**
	 * 计算2个时间相差的天数,这个方法算的是2个零点时间的绝对时间(天数)
	 * 
	 * @param startDate
	 *            起始时间
	 * @param endDate
	 *            结束时间
	 * @return 相差的天数
	 */
	public static int diffZeroDays(Date startDate, Date endDate) {
		int value = 0;
		if (startDate != null && endDate != null) {
			Date startDate0AM = getFirstTime(startDate);
			Date endDate0AM = getFirstTime(endDate);
			long diff = endDate0AM.getTime() - startDate0AM.getTime();
			value = (int) MathUtils.divideAndRoundUp(diff, MILLIS_PER_DAY, 0);
		}
		return value;
	}

	public static int diffYears(Date startDate, Date endDate) {

		Calendar start = Calendar.getInstance();
		start.setTime(startDate);

		Calendar end = Calendar.getInstance();
		end.setTime(endDate);

		return end.get(Calendar.YEAR) - start.get(Calendar.YEAR);
	}

	public static int diffMonths(Date startDate, Date endDate) {

		int diff = diffYears(startDate, endDate) * 12;

		Calendar start = Calendar.getInstance();
		start.setTime(startDate);

		Calendar end = Calendar.getInstance();
		end.setTime(endDate);

		return diff + end.get(Calendar.MONTH) - start.get(Calendar.MONTH);
	}

	public static int diffDays(Date startDate, Date endDate) {

		long value = endDate.getTime() - startDate.getTime();
		int result = (int) MathUtils.divideAndRoundUp(value, MILLIS_PER_DAY, 0);
		return result;
	}

	public static int diffHours(Date startDate, Date endDate) {

		long value = endDate.getTime() - startDate.getTime();
		int result = (int) MathUtils.divideAndRoundUp(value, MILLIS_PER_HOUR, 0);
		return result;
	}

	public static int diffMinutes(Date startDate, Date endDate) {

		long value = endDate.getTime() - startDate.getTime();
		int result = (int) MathUtils.divideAndRoundUp(value, MILLIS_PER_MINUTE, 0);
		return result;
	}

	public static int diffSeconds(Date startDate, Date endDate) {

		long value = endDate.getTime() - startDate.getTime();
		int result = (int) MathUtils.divideAndRoundUp(value, MILLIS_PER_SECOND, 0);
		return result;
	}

	/**
	 * 获取指定CRON表达式的下一个时间点
	 * 
	 * @param cron
	 *            CRON表达式
	 * @param now
	 *            基准时间点
	 * @return 下一个时间点
	 */
	public static Date getNextTime(String cron, Date now) {
		CronSequenceGenerator gen = new CronSequenceGenerator(cron, TimeZone.getDefault());
		Date time = gen.next(now);
		return time;
	}
	/**
	 * 获取服务器启动时间
	 */
	public static Date getServerStartDate()
	{
		long time = ManagementFactory.getRuntimeMXBean().getStartTime();
		return new Date(time);
	}
	/**
	 * 计算两个时间差
	 */
	public static String getDatePoor(Date endDate, Date nowDate)
	{
		long nd = 1000 * 24 * 60 * 60;
		long nh = 1000 * 60 * 60;
		long nm = 1000 * 60;
		// long ns = 1000;
		// 获得两个时间的毫秒时间差异
		long diff = endDate.getTime() - nowDate.getTime();
		// 计算差多少天
		long day = diff / nd;
		// 计算差多少小时
		long hour = diff % nd / nh;
		// 计算差多少分钟
		long min = diff % nd % nh / nm;
		// 计算差多少秒//输出结果
		// long sec = diff % nd % nh % nm / ns;
		return day + "天" + hour + "小时" + min + "分钟";
	}
	/**
	 * 时间戳转换成日期格式字符串
	 * @param seconds 精确到秒的字符串
	 * @param
	 * @return
	 */
	public static String timeStamp2DateStr(String seconds,String format) {
		if(seconds == null || seconds.isEmpty() || seconds.equals("null")){
			return "";
		}
		if(format == null || format.isEmpty()){
			format = "yyyy-MM-dd HH:mm:ss";
		}
		SimpleDateFormat sdf = new SimpleDateFormat(format);
		return sdf.format(new Date(Long.valueOf(seconds+"000")));
	}
	/**
	 * 日期格式字符串转换成时间戳
	 * @param
	 * @param format 如：yyyy-MM-dd HH:mm:ss
	 * @return
	 */
	public static String dateStr2TimeStamp(String date_str,String format){
		try {
			SimpleDateFormat sdf = new SimpleDateFormat(format);
			return String.valueOf(sdf.parse(date_str).getTime()/1000);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return "";
	}

	/**
	 * 判断日期格式是否正确
	 * @param date
	 * @return
	 */
	public static boolean isDate(String date) {
		if ("null" == date || date == "" || date.length() != 10) {
			return false;
		}
		String rexp = "^((\\d{2}(([02468][048])|([13579][26]))[\\-\\/\\s]?((((0?[13578])|(1[02]))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])))))|(\\d{2}(([02468][1235679])|([13579][01345789]))[\\-\\/\\s]?((((0?[13578])|(1[02]))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\-\\/\\s]?((0?[1-9])|(1[0-9])|(2[0-8]))))))";
		Pattern pat = Pattern.compile(rexp);
		Matcher mat = pat.matcher(date);
		boolean dateType = mat.matches();
		return dateType;
	}

	/**
	 * 秒转成时间
	 * @param second
	 * @return
	 */

	public static String getTime(int second) {

		String str = "";

		int diff_days = second / 86400;
		int diff_hours = (second - diff_days * 86400) / 3600;
		int diff_min = (second - diff_days * 86400 - diff_hours * 3600) / 60;
		int diff_sec = second % 60;

		if (diff_days > 0)
			str += diff_days + "天";

		if (diff_days > 0 || diff_hours > 0)
			str += diff_hours + "时";

		if (diff_days > 0 || diff_hours > 0 || diff_min > 0)
			str += diff_min + "分";

		if (diff_sec > 0 || str.isEmpty())
			str += diff_sec + "秒";
		return str;
	}

	public static String getLeftTime(Date start, Date end) {

		String str = "";
		int diff = DateUtils.diffMinutes(start, end);
		int diff_days = diff / (24 * 60);
		int diff_hours = diff % (24 * 60) / 60;
		int diff_min = diff % 60;

		if (diff_days > 0)
			str += diff_days + "天";

		if (diff_days > 0 || diff_hours > 0)
			str += diff_hours + "时";

		if (diff_min > 0)
			str += diff_min + "分";

		return str;
	}
}
